package com.jinke.api.modules.third.ebay;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ebay.api.client.auth.oauth2.CredentialUtil;
import com.ebay.api.client.auth.oauth2.OAuth2Api;
import com.ebay.api.client.auth.oauth2.model.Environment;
import com.ebay.api.client.auth.oauth2.model.OAuthResponse;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.modules.api.controller.StoreInfoRequest;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.ums.util.UserUtil;
import com.jinke.api.modules.user.model.UserToken;
import com.jinke.api.modules.user.service.UserTokenService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class EbayService {

    @Value("${ebay.baseUrl}")
    private String baseUrl;

    @Value("${ebay.identityUrl}")
    private String identityUrl;

    @Resource
    UserTokenService userTokenService;

    @Resource
    OrderService userOrderService;

    List<String> scopeList = new ArrayList<>();

    //判断是否生产环境
    @Value("${ebay.isSandbox}")
    private Boolean isSandBox;

    /*
     * 加载配置文件 必须
     */
    static {
        try {
            ClassPathResource classPathResource = new ClassPathResource("ebay-config.yaml");
            InputStream inputStream = classPathResource.getInputStream();
            CredentialUtil.load(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostConstruct
    public void init() {
        // 基础权限
        scopeList.add("https://api.ebay.com/oauth/api_scope");
        // 获取订单权限
        scopeList.add("https://api.ebay.com/oauth/api_scope/sell.fulfillment");
        scopeList.add("https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly");
        // 发货信息权限
        scopeList.add("https://api.ebay.com/oauth/api_scope/sell.fulfillment");
        //包裹信息
        scopeList.add("https://api.ebay.com/oauth/api_scope/sell.inventory.readonly");
        scopeList.add("https://api.ebay.com/oauth/api_scope/sell.inventory");
        //商户信息
        scopeList.add("https://api.ebay.com/oauth/api_scope/commerce.identity.readonly");
//        scopeList.add("https://api.ebay.com/oauth/api_scope/commerce.identity.name.readonly");
//        scopeList.add("https://api.ebay.com/oauth/api_scope/commerce.identity.address.readonly");
//        scopeList.add("https://api.ebay.com/oauth/api_scope/commerce.identity.email.readonly");
//        scopeList.add("https://api.ebay.com/oauth/api_scope/commerce.identity.phone.readonly");
    }

    /**
     * 获取授权地址
     *
     * @param request
     */
    public String getAuthorizaRestfulUrl(StoreInfoRequest request) {
        OAuth2Api oauth2Api = new OAuth2Api();
        String url = oauth2Api.generateUserAuthorizationUrl(Environment.PRODUCTION, scopeList, Optional.of(request.getStoreName()));
        userTokenService.saveToken(null, null, request.getStoreName(), request.getStoreType(), request.getStoreAccount());
        log.info(url);
        return url;
    }

    /**
     * 通过code获取token
     *
     * @param
     * @param
     * @return
     * @throws IOException
     */
    public CommonResult<String> getTokenByCode(StoreInfoRequest request) {
        OAuth2Api oauth2Api = new OAuth2Api();
        String token = null;
        String refreshToken = null;
        try {
            OAuthResponse oAuthResponse = oauth2Api.exchangeCodeForAccessToken(Environment.PRODUCTION, request.getCode());
            token = oAuthResponse.getAccessToken().get().getToken();
            refreshToken = oAuthResponse.getRefreshToken().get().getToken();
        } catch (Exception e) {
            log.error(e.getMessage());
            return CommonResult.failed("获取token失败");
        }
        log.info("refreshToken: " + refreshToken);
        log.info("token: " + token);
        //保存token
        UserToken userToken = getStoreInfo(token);
        if (!userToken.getStoreAccount().isEmpty()) {
            log.info(JSON.toJSONString(userToken));
            LambdaQueryWrapper<UserToken> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserToken::getStoreAccount, userToken.getStoreAccount());
            wrapper.eq(UserToken::getUserId,UserUtil.getUserInfo().getId());
            List<UserToken> list = userTokenService.list(wrapper);
            if (CollectionUtils.isEmpty(list)) {
                return CommonResult.failed("未找到对应商户账号");
            }
            UpdateWrapper<UserToken> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("store_account", userToken.getStoreAccount());
            updateWrapper.eq("user_id", UserUtil.getUserInfo().getId());
            updateWrapper.set("token", token);
            updateWrapper.set("refresh_token", refreshToken);
            updateWrapper.set("email", userToken.getEmail());
            userTokenService.update(updateWrapper);
        }
        return CommonResult.success();
    }

    /**
     * 获取商户信息
     *
     * @param token
     * @return
     */
    private UserToken getStoreInfo(String token) {
        UserToken userToken = new UserToken();
        String url = identityUrl + "/commerce/identity/v1/user/";
        final OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", String.format("Bearer %s", token))
                .build();
        final Response response;
        try {
            //配置okHttpClient超时时间
            response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                String result = response.body().string();
                log.info(result);
                String storeAccount = JSON.parseObject(result).get("username").toString();
                userToken.setStoreAccount(storeAccount);
                if(JSON.parseObject(result).containsKey("individualAccount")) {
                    String email = JSON.parseObject(JSON.parseObject(result).get("individualAccount").toString()).get("email").toString();
                    userToken.setEmail(email);
                }
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return userToken;
    }

    /**
     *
     */
    public CommonResult reRefreshToken(Integer storeId) throws IOException {
        //todo
        //从user_token表找出要更新的token，更新后存表
        if (Objects.isNull(storeId)) {
            return CommonResult.validateFailed();
        }
        UserToken userToken = userTokenService.getById(storeId);
        if (Objects.isNull(userToken)) {
            return CommonResult.validateFailed();
        }

        OAuth2Api oauth2Api = new OAuth2Api();

        try {
            OAuthResponse oAuthResponse = oauth2Api.getAccessToken(Environment.PRODUCTION, userToken.getRefreshToken(), scopeList);
            String token = oAuthResponse.getAccessToken().get().getToken();

            //存入user_token表
            userToken.setToken(token);
            userToken.setUpdatedAt(LocalDateTime.now());
            userTokenService.updateById(userToken);
            return CommonResult.success();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return CommonResult.failed();
    }


    /**
     * 获取订单信息.
     *
     * @param
     */
    public CommonResult<List<Order>> getOrders(Integer storeId) throws IOException {
        //todo 从user_token表取出token，获取订单信息
        if (Objects.isNull(storeId)) {
            return CommonResult.validateFailed();
        }
        UserToken userToken = userTokenService.getById(storeId);
        if (Objects.isNull(userToken)) {
            return CommonResult.validateFailed();
        }

        String accessToken = userToken.getToken();
        String orderUrl = baseUrl + "/sell/fulfillment/v1/order?limit=%s&offset=%s";
        String url = String.format(orderUrl, "50", "0");
        log.info(url);

        final OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", String.format("Bearer %s", accessToken))
                .build();
        final Response response = okHttpClient.newCall(request).execute();
        //todo 解析订单信息存入user_order表 订单的id  order_type=2
        String result = response.body().string();
        log.info(result);

        userOrderService.handleOrders(result);

        List<Order> orders = new ArrayList<>();
        return CommonResult.success(orders);
    }


    /**
     * 更新发货信息.
     */
    public void putPackage(String orderId, String storeId) {
        //todo 从user_token表取出token，更新发货信息
        String accessToken = "";
        List<Map<String, Object>> lineItems = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();
        item.put("lineItemId", "12");
        item.put("quantity", 1);
        lineItems.add(item);

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("lineItems", lineItems);
        bodyMap.put("shippedDate", this.getISO8601Timestamp(0));
        // 承运人唯一标识
        bodyMap.put("shippingCarrierCode", "");
        // 承运人跟踪编号
        bodyMap.put("trackingNumber", "");

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaType.get("application/json"));

        String packageUrl = baseUrl + "/sell/fulfillment/v1/order/%s/shipping_fulfillment";
        final OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(String.format(packageUrl, "1"))
                .post(body)
                .addHeader("Authorization", String.format("Bearer %s", accessToken))
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            log.info(response.body().string());
            System.out.println();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public CommonResult changeEnv() {
        isSandBox = !isSandBox;
        return CommonResult.success(isSandBox?"切换到沙箱环境":"切换到生产环境");
    }

    /**
     * 传入Data类型日期，返回字符串类型时间（ISO8601标准时间）
     *
     * @param
     * @return
     */
    public String getISO8601Timestamp(Integer days) {
        Date now = new Date();
        Date startDate = DateUtils.addDays(now, days);
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        df.setTimeZone(tz);
        String nowAsISO = df.format(startDate);
        return nowAsISO;
    }


}
